package com.acmedcare.framework.exchange.center.core.handler;

import com.acmedcare.framework.exchange.center.core.PluginContainerMBean;
import com.acmedcare.framework.exchange.center.core.PluginMetadata;
import com.acmedcare.framework.exchange.center.core.adapter.AdapterMetadata;
import com.acmedcare.framework.exchange.center.core.exception.PluginNotFoundException;
import com.acmedcare.framework.exchange.center.core.metadata.IDataAdapter;
import com.acmedcare.framework.exchange.center.core.metadata.Response;
import com.acmedcare.framework.exchange.center.core.metadata.ResponseConvert;
import com.acmedcare.framework.exchange.center.entity.bean.PluginStatusEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.HashMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;


@SuppressWarnings("unused")
@Slf4j
public class PluginHandler implements PluginHandlerMBean {

  private final ObjectMapper objectMapper;
  private final PluginContainerMBean pluginContainer;

  public PluginHandler(ObjectMapper objectMapper,
      PluginContainerMBean pluginContainer) {
    this.objectMapper = objectMapper;
    this.pluginContainer = pluginContainer;
  }

  @Override
  public ResponseConvert invoke(Request request) throws Exception {

    validRequest(request);

    try {

      PluginMetadata metadata = pluginContainer.getPlugin(request.getPluginName());
      if (!metadata.getStatus().equals(PluginStatusEnum.LOADED)) {

        return new ResponseConvert(HttpStatus.SERVICE_UNAVAILABLE.value(), "所请求的适配正在加载或者卸载，请稍后再试!");
      }

      AdapterMetadata adapterMetadata = metadata.getAdapterMetadata()
          .get(URLDecoder.decode(request.getUrl()).toLowerCase().trim());

      if (adapterMetadata == null) {

        return new ResponseConvert(HttpStatus.BAD_REQUEST.value(), "未能找到相应的适配器，请确认后再试!");
      }

      Class<?> adapterMetadataClass = adapterMetadata.getAdapterClass();
      IDataAdapter adapter = adapterMetadata.getInstance();

      if (adapter == null) {

        adapter = (IDataAdapter) adapterMetadataClass.newInstance();
        adapterMetadata.setInstance(adapter);
      }

      switch (request.getHttpMethod()) {

        case GET:

          Response response = adapter.get(request.getParameters());

          return new ResponseConvert(response.getStatus(),
              objectMapper.writeValueAsString(response.getBody()));
        default:

          if (adapterMetadata.getMethods() == null) {

            HashMap<String, Method> methods = new HashMap<>();
            for (Method method : adapterMetadataClass.getMethods()) {

              if (method.getParameterCount() == 1) {

                methods.put(method.getName().toLowerCase(), method);
              }
            }

            adapterMetadata.setMethods(methods);
          }

          String methodName = request.getHttpMethod().name().toLowerCase();
          Object obj = adapterMetadata.getMethods().get(methodName);

          if (obj == null) {

            return new ResponseConvert(HttpStatus.BAD_REQUEST.value(), "该请求方式，适配器尚未");
          }

          Method method = (Method) obj;
          Class<?> type = method.getParameterTypes()[0];
          Object body = null;
          if (request.getBody() != null) {

            body = objectMapper.readValue(request.getBody(), type);
          }

          response = (Response) method.invoke(adapter, body);

          return new ResponseConvert(response.getStatus(),
              objectMapper.writeValueAsString(response.getBody()));
      }
    } catch (PluginNotFoundException e) {

      return new ResponseConvert(HttpStatus.BAD_REQUEST.value(), "未能找到合适的插件加载，请确认，插件是否已经卸载！");
    } catch (Exception e) {

      log.error("请求处理错误", e);
    }

    return new ResponseConvert(HttpStatus.BAD_REQUEST.value(), "请求错误，请稍后再试！");
  }

  private void validRequest(Request request) throws Exception {

    if (StringUtils.isEmpty(request.getPluginName())) {

      throw new Exception("插件不允许为空！");
    }

    if (StringUtils.isEmpty(request.getUrl())) {

      throw new Exception("适配器名称不允许为空！");
    }

    if (request.getHttpMethod() == null) {

      throw new Exception("请求方法不允许为空!");
    }
  }
}
